home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / comm / bbs / cit_src_AD08.lha / confg.c < prev    next >
C/C++ Source or Header  |  1998-06-14  |  46KB  |  1,849 lines

  1. /*
  2. *           confg.c
  3. *
  4. * Configuration program for Citadel bulletin board system.
  5. */
  6. #define CONFIGURE
  7. #include "ctdl.h"
  8. #include "math.h"
  9. /*
  10. *       History
  11. *
  12. * 85Dec26 HAW  Add CALL-LOG define.
  13. * 85Nov15 HAW  MS-DOS library update.
  14. * 85Oct27 HAW  Kill CERMETEK.
  15. * 85Oct17 HAW  Add paramVers, change bauds to array, searchBaud chg.
  16. * 85Oct16 HAW  Kill CLOCK, add officeStuff.
  17. * 85Aug24 HAW  Add duomessage file, NETDISK specification.
  18. * 85Jul07 HAW  Update so won't go through total recon. on init.
  19. * 85May27 HAW  Start stuffing in auto-networking stuff.
  20. * 85May22 HAW  Start conversion to make log file size sysop selectable.
  21. * 85May11 HAW  Make "Lobby" sysop definable
  22. * 85May06 HAW  Add bail out code.
  23. * 85May05 HAW  Add helpDisk parameter for 3 disk system.
  24. * 85Apr10 HAW  Fix logSort, alphabetize file.
  25. * 85Mar11 HAW  Put all user functions in this file.
  26. * 85Feb18 HAW  Add baud search stuff.
  27. * 85Jan20 HAW  Use MSDOS #define for date stuff.
  28. * 84Sep05 HAW  Isolate strangeness in compiler's library.  See note.
  29. * 84Aug30 HAW  Onwards to MS-DOS!
  30. * 84Apr08 HAW  Update to BDS C 1.50a begun.
  31. * 82Nov20 CrT  Created.
  32. */
  33. /*
  34. *       Contents
  35. *
  36. * dGetWord()    reads a word off disk
  37. * init()      system startup initialization
  38. * main()      main controller
  39. * illegal()   abort bottleneck
  40. * msgInit()   sets up cfg.catChar, catSect etc.
  41. * zapMsgFile()    initialize ctdlmsg.sys
  42. * realZap()   does work of zapMsgFile()
  43. * indexRooms()    build RAM index to ctdlroom.sys
  44. * noteRoom()    enter room into RAM index
  45. * zapRoomFile()   erase & re-initialize ctdlroom.sys
  46. * setSpace()    set default disk and user#
  47. * hash()      hashes a string to an integer
  48. * logInit()   builds the RAM index to CTDLLOG.SYS
  49. * noteLog()   enters a userlog record into RAM index
  50. * sortLog()   sort CTDLLOG by time since last call
  51. * wrapup()    finishes and writes ctdlTabl.sys
  52. * zapLogFile()    erases & re-initializes CTDLLOG.SYS
  53. */
  54. /*
  55. *   Strangenesses   (Hue, Jr., 12Sep84)
  56. * Have discovered that the line:
  57. * sscanf(line, "\"%s\"", str);
  58. * is not parsed the same way by this compiler as it is by BDS;
  59. * this is highly unfortunate and excrable.  So, all porters
  60. * should note that scanf() is not, in any way, "portable."  If
  61. * BDS is "non-standard", then the standard sucks.
  62. */
  63. #define BAUDS "Valid SYSBAUD values: 0=300, 1=1200, 2=2400, 3=4800,\n4=9600, 5=14.4, 6=19.2, 7=38.4, 8=57.6"
  64. struct GenList
  65.   {
  66.   char *GenName;
  67.   int  GenVal;
  68.  
  69.   };
  70. extern FILE *msgfl, *msgfl2;    /* file descriptor for the msg file */
  71.  
  72. FILE *netLog=stdout;
  73. char   *baseRoom;
  74. int   mailCount=0;
  75. char   msgZap =  FALSE,
  76. logZap =  FALSE,
  77. roomZap = FALSE;
  78. char  FirstInit = FALSE;
  79. char  ReInit = FALSE;
  80. static DATA_BLOCK sectBuf;
  81. long FloorSize;
  82. int  DefaultPrefix;
  83. void  Zap_Nodes_Message_Index(void);  /* zap last netted message */
  84.  
  85.  
  86. static char NetParse(char *line, int *offset, char *var, int arg, int SetVal);
  87. extern SListBase Events;    /* event list     */
  88. extern CONFIG    cfg;      /* The configuration variable  */
  89. extern MessageBuffer   msgBuf;    /* The -sole- message buffer  */
  90. extern NetBuffer netBuf;
  91. extern rTable    *roomTab;        /* RAM index of rooms   */
  92. extern aRoom     roomBuf;        /* room buffer     */
  93. extern EVENT     *EventTab;
  94. extern int       thisRoom;        /* room currently in roomBuf  */
  95. extern int       thisNet;
  96. extern LogTable  *logTab;        /* RAM index of pippuls    */
  97. extern logBuffer logBuf;    /* Log buffer of a person       */
  98. extern SListBase Serves;
  99. extern FILE      *logfl;    /* log file descriptor    */
  100. extern FILE      *roomfl;        /* file descriptor for rooms */
  101. extern FILE      *netfl;
  102. extern LogTable  *logTab;        /* RAM index of pippuls    */
  103. extern int       thisLog;        /* entry currently in logBuf */
  104. extern NetTable  *netTab;
  105. void CheckNet( void );
  106. /*
  107. * init()
  108. *
  109. * The master system initialization.
  110. */
  111. void init(int attended)
  112.   {
  113.   extern char   *W_R_ANY;
  114.   extern char   *R_W_ANY;
  115.   extern char   *READ_ANY;
  116.   extern char   *WRITE_ANY;
  117.   unsigned char c;
  118.   SYS_FILE      tempName;
  119.   extern int    errno, _doserrno;
  120.   cfg.sizeLTentry           = sizeof(*logTab);
  121.   cfg.BoolFlags.debug       = FALSE;
  122.   cfg.BoolFlags.DFDATE      = 0;
  123.   cfg.BoolFlags.LGDATE      = 0;
  124.   cfg.BoolFlags.tdebug      = 0;
  125.   cfg.BoolFlags.noChat      = TRUE;
  126.   /* shave-and-a-haircut/two bits pause pattern for ringing sysop: */
  127.   cfg.shave[0]    = 40;
  128.   cfg.shave[1]    = 20;
  129.   cfg.shave[2]    = 20;
  130.   cfg.shave[3]    = 40;
  131.   cfg.shave[4]    = 80;
  132.   cfg.shave[5]    = 40;
  133.   cfg.shave[6]    =250;
  134.   /* initialize input character-translation table:  */
  135.   for (c = 0;  c < '\40';  c++)
  136.     {
  137.     cfg.filter[c] = '\0';    /* control chars -> nulls  */
  138.  
  139.     }
  140.   cfg.filter[1] = 'y';    /* fix from 3.43, carried back to this version */
  141.   cfg.filter[7] = '7';
  142.   for (c='\40'; c < 128;   c++)
  143.     {
  144.     cfg.filter[c] = c;        /* pass printing chars  */
  145.  
  146.     }
  147.   cfg.filter[SPECIAL]     = SPECIAL;
  148.   cfg.filter[CNTRLl]      = CNTRLl;
  149.   cfg.filter[DEL      ]   = BACKSPACE;
  150.   cfg.filter[BACKSPACE]   = BACKSPACE;
  151.   cfg.filter[XOFF     ]   = XOFF     ;
  152.   cfg.filter[XON      ]   = XON      ;
  153.   cfg.filter['\r'     ]   = NEWLINE  ;
  154.   cfg.filter[CNTRLO   ]   = 'N'      ;
  155.   mvToHomeDisk(&cfg.homeArea);
  156.   makeSysName(tempName, "ctdlmsg.sys",  &cfg.msgArea);
  157.   if ((msgfl = fopen(tempName, R_W_ANY)) == NULL)
  158.     {
  159.     if (!attended)illegal("!System must be attended(ctdlmsg.sys) for creation!");
  160.     printf(" %s not found, creating new file. \n", tempName);
  161.     if ((msgfl = fopen(tempName, W_R_ANY)) == NULL)    illegal("?Can't create the message file!");
  162.     printf(" (Be sure to initialize it!)\n");
  163.  
  164.     }
  165.   makeSysName(tempName, "ctdllog.sys", &cfg.logArea);
  166.   /* open userlog file */
  167.   if ((logfl = fopen(tempName, R_W_ANY)) == NULL)
  168.     {
  169.     if (!attended)illegal("!System must be attended(ctdllog.sys) for creation!");
  170.     printf(" %s not found, creating new file. \n", tempName);
  171.     if ((logfl = fopen(tempName, W_R_ANY)) == NULL) illegal("?Can't create log file!");
  172.     printf(" (Be sure to initialize it!)\n");
  173.  
  174.     }
  175.   makeSysName(tempName, "ctdlroom.sys", &cfg.roomArea);
  176.   /* open room file */
  177.   if ((roomfl = fopen(tempName, R_W_ANY)) == NULL)
  178.     {
  179.     if (!attended)illegal("!System must be attended(ctdlroom.sys) for creation!");
  180.     printf(" %s not found, creating new file. \n", tempName);
  181.     if ((roomfl = fopen(tempName, W_R_ANY)) == NULL) illegal("?Can't create room file!");
  182.     printf(" (Be sure to initialize it!)\n");
  183.  
  184.     }
  185.   if (cfg.BoolFlags.netParticipant)
  186.     {
  187.     makeSysName(tempName, "ctdlnet.sys", &cfg.netArea);
  188.     if ((netfl = fopen(tempName, READ_ANY)) == NULL)
  189.       {
  190.       printf(" %s not found, creating new file.\n", tempName);
  191.       if ((netfl = fopen(tempName, WRITE_ANY)) == NULL)illegal("?Can't create the net file!");
  192.  
  193.       }
  194.  
  195.     }
  196.   CheckFloors();
  197.   if (attended || FirstInit)
  198.     {
  199.     char cx;
  200.     printf("\n Erase and initialize log, message and/or room files?");
  201.     cx = simpleGetch();
  202.     if (FirstInit || toUpper(cx)  == 'Y')
  203.       {
  204.       /* each of these has an additional go/no-go interrogation: */
  205.       msgZap  = zapMsgFile();
  206.       roomZap = zapRoomFile();
  207.       logZap  = zapLogFile();
  208.  
  209.       }
  210.  
  211.     }
  212.  
  213.   }
  214. /*
  215. * main()
  216. *
  217. * Main manager for confg.c.
  218. */
  219. int main(int, char **);
  220. int main(int argc, char **argv)
  221.   {
  222.   FILE *fBuf, *pwdfl;
  223.   char line[90], status, *strchr(), *g;
  224.   char onlyParams = FALSE, CleanCalllog;
  225.   char var[90];
  226.   int  arg;
  227.   int  i, offset = 1;
  228.   extern char *READ_TEXT;
  229.   int  SetVal;
  230.   if (argc > 1)
  231.     {
  232.     if (strCmpU(argv[1], "exists") == 0)
  233.       {
  234.       fBuf = fopen("exists", "w");
  235.       fprintf(fBuf, "I exist.");
  236.       fclose(fBuf);
  237.       exit(1);
  238.  
  239.       }
  240.  
  241.     }
  242.   cfg.paramVers = 12;
  243.   printf("%s Configurator (V%d.8) %s\n%s\n\n", VARIANT_NAME,
  244.   cfg.paramVers,VERSION_NAME, COPYRIGHT);
  245.   if (access(LOCKFILE, 0) != -1)
  246.     {
  247.     char cx;
  248.     printf(
  249.     "You are apparently reconfiguring from within Citadel, which is a No No!\n"
  250.     "Do you wish to continue? ");
  251.     cx = simpleGetch();
  252.     if (toUpper(cx) != 'Y')
  253.     exit(7);
  254.     unlink(LOCKFILE);
  255.  
  256.     }
  257.   zero_struct(cfg);
  258.   for (i = 1;  i < argc; i++)
  259.     {
  260.     if (strCmpU(argv[i], "onlyParams") == SAMESTRING )
  261.       onlyParams = TRUE;
  262.     else if (strCmpU(argv[i], "FirstInit") == SAMESTRING)
  263.       FirstInit = TRUE;
  264.     else if (strCmpU(argv[i], "ReInit") == SAMESTRING)
  265.       ReInit = TRUE;
  266.     else if( argv[i][0] == '-' )
  267.       {
  268.       switch (argv[i][1])
  269.         {
  270.         case 'o':   /* Only Parameters */
  271.         case 'O':   onlyParams = TRUE; break;
  272.         case 'F':   /* First Initialization */
  273.         case 'I':
  274.         case 'f':
  275.         case 'i':   FirstInit = TRUE; break;
  276.         case 'r':   /* Re-Initialization */
  277.         case 'R':   ReInit = TRUE; break;
  278.         default:
  279.           fprintf(stderr,"Parameter Error, Assuming ReInit\n");
  280.           ReInit = TRUE;
  281.         };
  282.       }
  283.     else if (!sysArgs(argv[i]))
  284.       ReInit = TRUE;
  285.     }
  286.   cfg.weAre     = CONFIGUR;
  287.   if (!(SetVal = readSysTab(FALSE, FALSE)))
  288.     {
  289.     cfg.sysPassword[0] = 0;
  290.     cfg.MAXLOGTAB = 0;      /* Initialize, just in case   */
  291.     cfg.ConTimeOut = -1;  /* optional parameter */
  292.     if (onlyParams)
  293.       {
  294.       printf("'onlyParams' parameter ignored, unable to read CTDLTABL.SYS\n");
  295.       onlyParams = FALSE;
  296.  
  297.       }
  298.  
  299.     }
  300.   else
  301.     {
  302.     if (EventTab != NULL) free(EventTab);
  303.     i = cfg.BoolFlags.noChat;
  304.     zero_struct(cfg.BoolFlags);
  305.     cfg.BoolFlags.noChat = i;
  306.  
  307.     }
  308.   cfg.paramVers = 12;   /* yes, set it twice*   */
  309.   InitBuffers();        /* initializes message buffers */
  310.   initSysSpec();        /* Call implementation specific code  */
  311.   /* these are mostly optional param values */
  312.   cfg.SysopName[0]     = 0;
  313.   cfg.SysopArchive[0]  = 0;
  314.   strCpy(cfg.DomainDisplay, " _ %s");
  315.   cfg.InitColumns      = 40;
  316.   cfg.BoolFlags.IsDoor = FALSE;
  317.   cfg.BoolFlags.NetScanBad = FALSE;
  318.   cfg.EvNumber   = 0;
  319.   cfg.MailHub    = 0;
  320.   cfg.DomainHandlers   = 0;
  321.   KillList(&Serves);
  322.   CleanCalllog   = FALSE;
  323.   cfg.Audit     = 0;
  324.   cfg.BoolFlags.RouteMail  = TRUE;
  325.   cfg.BoolFlags.DL_Default = TRUE;
  326.   cfg.AnonMailLength   = 0;
  327.   cfg.LoginAttempts    = 0;
  328.   zero_array(cfg.DialPrefixes);
  329.   cfg.MailHub   = 0;
  330.   EventTab = NULL;
  331.   if ((fBuf = fopen("ctdlcnfg.sys", READ_TEXT)) == NULL)
  332.     {
  333.     /* ASCII mode   */
  334.     printf("Error: Can't open ctdlCnfg.sys!\n");
  335.     perror("fopen");
  336.     poserr("fopen");
  337.     exit(1);
  338.  
  339.     }
  340.   while (fgets(line, 90, fBuf) != NULL)
  341.     {
  342.     if (line[0] != '#') continue;
  343.     if (sscanf(line, "%s %d ", var, &arg))
  344.       {
  345.       printf("%s", line);
  346.       if (NetParse(line, &offset, var, arg, SetVal))
  347.         {
  348.         continue;
  349.  
  350.         }
  351.       else if (strCmpU(var, "#CRYPTSEED" )    == SAMESTRING)
  352.         {
  353.         cfg.cryptSeed   = arg;
  354.  
  355.         }
  356.       else if (strCmpU(var, "#MESSAGEK"  )    == SAMESTRING)
  357.         {
  358.         cfg.maxMSector  = arg*(1024/MSG_SECT_SIZE);
  359.  
  360.         }
  361.       else if (strCmpU(var, "#LOGINOK"   )    == SAMESTRING)
  362.         {
  363.         cfg.BoolFlags.unlogLoginOk= arg;
  364.  
  365.         }
  366.       else if (strCmpU(var, "#ISDOOR"   )    == SAMESTRING)
  367.         {
  368.         cfg.BoolFlags.IsDoor = TRUE;
  369.  
  370.         }
  371.       else if (strCmpU(var, "#DoorPrivs")     == SAMESTRING)
  372.         {
  373.         cfg.BoolFlags.DoorDft     = arg;
  374.  
  375.         }
  376.       else if (strCmpU(var, "#FILE-PRIV-DEFAULT")     == SAMESTRING)
  377.         {
  378.         cfg.BoolFlags.DL_Default     = arg;
  379.  
  380.         }
  381.       else if (strCmpU(var, "#ENTEROK"   )    == SAMESTRING)
  382.         {
  383.         cfg.BoolFlags.unlogEnterOk= arg;
  384.  
  385.         }
  386.       else if (strCmpU(var, "#READOK"    )    == SAMESTRING)
  387.         {
  388.         cfg.BoolFlags.unlogReadOk = arg;
  389.  
  390.         }
  391.       else if (strCmpU(var, "#ROOMOK"    )    == SAMESTRING)
  392.         {
  393.         cfg.BoolFlags.nonAideRoomOk=arg;
  394.  
  395.         }
  396.       else if (strCmpU(var, "#ALLMAIL"   )    == SAMESTRING)
  397.         {
  398.         cfg.BoolFlags.noMail      = !arg;
  399.  
  400.         }
  401.       else if (strCmpU(var, "#UNLOGGED-WIDTH") == SAMESTRING)
  402.         {
  403.         cfg.InitColumns = arg;
  404.  
  405.         }
  406.       else if (strCmpU(var, "#LOGIN-ATTEMPTS") == SAMESTRING)
  407.         {
  408.         cfg.LoginAttempts = arg;
  409.  
  410.         }
  411.       else if (strCmpU(var, "#ANON-MAIL-LENGTH") == SAMESTRING)
  412.         {
  413.         cfg.AnonMailLength = arg;
  414.  
  415.         }
  416.       else if (strCmpU(var, "#CLEAN-CALLLOG") == SAMESTRING)
  417.         {
  418.         CleanCalllog = TRUE;
  419.  
  420.         }
  421.       else if (strCmpU(var, "#ANONYMOUS-SESSIONS") == SAMESTRING)
  422.         {
  423.         cfg.BoolFlags.AnonSessions = TRUE;
  424.  
  425.         }
  426.       else if (strCmpU(var, "#MIRRORMSG" )    == SAMESTRING)
  427.         {
  428.         cfg.BoolFlags.mirror = arg;
  429.  
  430.         }
  431.       else if (strCmpU(var, "#LOGSIZE"   )    == SAMESTRING)
  432.         {
  433.         if (SetVal)
  434.           {
  435.           if (cfg.MAXLOGTAB != arg)
  436.           illegal(
  437.           "LOGSIZE parameter does not equal old value!");
  438.  
  439.           }
  440.         else
  441.           {
  442.           cfg.MAXLOGTAB   = arg;
  443.           logTab = (LogTable *)
  444.           GetDynamic(sizeof(*logTab) * arg);
  445.  
  446.           }
  447.  
  448.         }
  449.       else if (strCmpU(var, "#MAXROOMS"  )    == SAMESTRING)
  450.         {
  451.         if (SetVal)
  452.           {
  453.           if (MAXROOMS != arg)
  454.           illegal(
  455.           "MAXROOMS parameter does not equal old value!");
  456.  
  457.           }
  458.         else
  459.           {
  460.           MAXROOMS = arg;
  461.           if (MAXROOMS <= 3)
  462.           illegal("MAXROOMS must be greater than 3!");
  463.           roomTab = (rTable *)
  464.           GetDynamic(MAXROOMS * sizeof *roomTab);
  465.  
  466.           }
  467.  
  468.         }
  469.       else if (strCmpU(var, "#MSG-SLOTS" )    == SAMESTRING)
  470.         {
  471.         if (SetVal)
  472.           {
  473.           if (MSGSPERRM != arg)
  474.           illegal(
  475.           "MSGSPERRM parameter does not equal old value!");
  476.  
  477.           }
  478.         else
  479.           {
  480.           MSGSPERRM = arg;
  481.  
  482.           }
  483.  
  484.         }
  485.       else if (strCmpU(var, "#MAIL-SLOTS")    == SAMESTRING)
  486.         {
  487.         if (SetVal)
  488.           {
  489.           if (MAILSLOTS != arg)
  490.           illegal(
  491.           "MAILSLOTS parameter does not equal old value!");
  492.  
  493.           }
  494.         else
  495.           {
  496.           MAILSLOTS = arg;
  497.  
  498.           }
  499.  
  500.         }
  501.       else if (strCmpU(var, "#AIDESEEALL")    == SAMESTRING)
  502.         {
  503.         cfg.BoolFlags.aideSeeAll = arg;
  504.  
  505.         }
  506.       else if (strCmpU(var, "#CONSOLE-TIMEOUT")    == SAMESTRING)
  507.         {
  508.         cfg.ConTimeOut = arg;
  509.  
  510.         }
  511.       else if (strCmpU(var, "#SYSBAUD"   )    == SAMESTRING)
  512.         {
  513.         cfg.sysBaud   = arg;
  514.         if (arg > 8 || arg < 0)
  515.           {
  516.           illegal(BAUDS);
  517.  
  518.           }
  519.  
  520.         }
  521.       else if (strCmpU(var, "#event"    ) == SAMESTRING)
  522.         {
  523.         offset = EatEvent(line, offset);
  524.  
  525.         }
  526.       else if (strCmpU(var, "#nodeTitle") == SAMESTRING)
  527.         {
  528.         readString(line, &cfg.codeBuf[offset], TRUE);
  529.         cfg.nodeTitle = offset;
  530.         while (cfg.codeBuf[offset])
  531.         offset++;
  532.         offset++;
  533.  
  534.         }
  535.       else if (strCmpU(var, "#sysPassword") == SAMESTRING)
  536.         {
  537.         readString(line, cfg.sysPassword, FALSE);
  538.         if ((pwdfl = fopen(cfg.sysPassword, READ_TEXT)) == NULL)
  539.           {
  540.           printf("\nNo system password file found\n");
  541.           cfg.sysPassword[0] = 0;
  542.  
  543.           }
  544.         else
  545.           {
  546.           fgets(cfg.sysPassword, 199, pwdfl);
  547.           /*  cfg.sysPassword[strLen(cfg.sysPassword) - 1] = 0;*/
  548.           while ((g = strchr(cfg.sysPassword, '\n')) != NULL)
  549.           *g = 0;
  550.           if (strLen(cfg.sysPassword) < 15)
  551.             {
  552.             printf("\nSystem password is too short -- ignored\n");
  553.             cfg.sysPassword[0] = 0;
  554.  
  555.             }
  556.           fclose(pwdfl);
  557.  
  558.           }
  559.  
  560.         }
  561.       else if (strCmpU(var, "#sysopName") == SAMESTRING)
  562.         {
  563.         readString(line, msgBuf.mbtext, FALSE);
  564.         if (strLen(msgBuf.mbtext) > 19)
  565.         illegal("SysopName too long; must be less than 20");
  566.         strCpy(cfg.SysopName, msgBuf.mbtext);
  567.  
  568.         }
  569.       else if (strCmpU(var, "#SYSOP-ARCHIVE") == SAMESTRING)
  570.         {
  571.         readString(line, msgBuf.mbtext, FALSE);
  572.         if (strLen(msgBuf.mbtext) > sizeof cfg.SysopArchive)
  573.           {
  574.           sprintf(msgBuf.mbtext, "SysopName too long; must be less than %d", sizeof cfg.SysopArchive);
  575.           illegal(msgBuf.mbtext);
  576.  
  577.           }
  578.         strCpy(cfg.SysopArchive, msgBuf.mbtext);
  579.  
  580.         }
  581.       else if (strCmpU(var, "#baseRoom") == SAMESTRING)
  582.         {
  583.         readString(line, &cfg.codeBuf[offset], TRUE);
  584.         if (strLen(&cfg.codeBuf[offset]) > 19)
  585.         illegal("baseRoom too long; must be less than 20");
  586.         cfg.bRoom = offset;
  587.         baseRoom = &cfg.codeBuf[offset];
  588.         while (cfg.codeBuf[offset])
  589.         offset++;
  590.         offset++;
  591.  
  592.         }
  593.       else if (strCmpU(var, "#MainFloor") == SAMESTRING)
  594.         {
  595.         readString(line, &cfg.codeBuf[offset], TRUE);
  596.         if (strLen(&cfg.codeBuf[offset]) > 19)
  597.         illegal("#MainFloor too long; must be less than 20");
  598.         cfg.MainFloor = offset;
  599.         while (cfg.codeBuf[offset])
  600.         offset++;
  601.         offset++;
  602.  
  603.         }
  604.       else if (strCmpU(var, "#alldone") == SAMESTRING)
  605.         {
  606.         break;
  607.  
  608.         }
  609.       else
  610.         {
  611.         offset = sysSpecs(line, offset, &status, fBuf);
  612.         if (!status)
  613.         printf("? -- no variable '%s' known! -- ignored.\n", var);
  614.  
  615.         }
  616.  
  617.       }
  618.  
  619.     }
  620.   for (i = 0; i <= B_7; i++)
  621.   if (cfg.DialPrefixes[i] == 0)
  622.     {
  623.     cfg.DialPrefixes[i] = DefaultPrefix;
  624.  
  625.     }
  626.   if (cfg.Audit == 1)
  627.   if (CleanCalllog) cfg.Audit = 2;
  628.   initLogBuf(&logBuf);
  629.   initRoomBuf(&roomBuf);
  630.   initNetBuf(&netBuf);
  631.   if (!SysDepIntegrity(&offset))  exit(100);
  632.   RunList(&Events, EvIsDoor);
  633.   printf("offset=%d\n", offset);
  634.   if (offset < MAXCODE)
  635.     {
  636.     if (!onlyParams) init(!ReInit);
  637.     else
  638.       {
  639.       CheckFloors();
  640.       if (cfg.BoolFlags.netParticipant)
  641.       CheckNet();
  642.  
  643.       }
  644.     wrapup(onlyParams);
  645.  
  646.     }
  647.   else
  648.     {
  649.     illegal(
  650.     "\7codeBuf[] overflow! Recompile with larger MAXCODE or reduce ctdlCnfg.sys\7"
  651.     );
  652.  
  653.     }
  654.   return 0;
  655.  
  656.   }
  657. /*
  658. * readString()
  659. *
  660. * This function reads a '#<id> "<value>"  since scanf can't.
  661. */
  662. void readString(char *source, char *destination, char doProc)
  663.   {
  664.   char string[300], last = 0;
  665.   int  i, j;
  666.   for (i = 0; source[i] != '"' && source[i]; i++)
  667.   ;
  668.   if (!source[i])
  669.     {
  670.     sPrintf(string, "Couldn't find beginning \" in -%s-", source);
  671.     illegal(string);
  672.  
  673.     }
  674.   for (j = 0, i++; source[i] &&
  675.   (source[i] != '"' || (doProc && last == '\\'));
  676.   i++, j++)
  677.     {
  678.     string[j] = source[i];
  679.     last = source[i];
  680.  
  681.     }
  682.   if (!source[i])
  683.     {
  684.     sPrintf(string, "Couldn't find ending \" in -%s-", source);
  685.     illegal(string);
  686.  
  687.     }
  688.   string[j] = '\0';
  689.   strCpy(destination, string);
  690.   if (doProc) xlatfmt(destination);
  691.  
  692.   }
  693. /*
  694. * isoctal() * xlatfmt()
  695. *
  696. * contributed by Dale Schumacher, allow embedding of formatting info a la'
  697. * "C" style: \n, \t, etc....
  698. */
  699. char isoctal( int c )
  700.   {
  701.   return  (char)(( c >= '0' ) && ( c <= '7' ));
  702.  
  703.   }
  704. void xlatfmt( char *s )
  705.   {
  706.   register char *p, *q;
  707.   register int i;
  708.   for( p=q=s; *q; ++q )
  709.     {
  710.     if ( *q == '\\' )
  711.     switch( *++q )
  712.       {
  713.       case 'n' :
  714.       *p++ = '\n';
  715.       break;
  716.       case 't' :
  717.       *p++ = '\t';
  718.       break;
  719.       case 'r' :
  720.       *p++ = '\r';
  721.       break;
  722.       case 'f' :
  723.       *p++ = '\f';
  724.       break;
  725.       default :
  726.       if ( isoctal( *q ))
  727.         {
  728.         i = (( *q++ ) - '0' );
  729.         if ( isoctal( *q ))
  730.           {
  731.           i <<= 3;
  732.           i += (( *q++ ) - '0' );
  733.           if ( isoctal( *q ))
  734.             {
  735.             i <<= 3;
  736.             i += (*q -'0');
  737.  
  738.             }
  739.           else
  740.           --q;
  741.  
  742.           }
  743.         else
  744.         --q;
  745.         *p++ = 0xFF & ((char) i);
  746.  
  747.         }
  748.       else
  749.       *p++ = *q;
  750.       break;
  751.  
  752.       }
  753.     else
  754.     *p++ = *q;
  755.  
  756.     }
  757.   *p = '\0';
  758.  
  759.   }
  760. /*
  761. * illegal()
  762. *
  763. * This will print out configure error message and aborts.
  764. */
  765. void illegal(char *errorstring)
  766.   {
  767.   printf("\007\nERROR IN CONFIGURATION:\n%s\nABORTING", errorstring);
  768.   exit(100);
  769.  
  770.   }
  771. /*
  772. * dGetWord()
  773. *
  774. * This fetches one word from current message, off disk, returns TRUE if more
  775. * words follow, else FALSE.
  776. */
  777. char dGetWord(char *dest, int lim)
  778.   {
  779.   char c;
  780.   --lim;      /* play it safe */
  781.   /* pick up any leading blanks: */
  782.   for (c = getMsgChar();   c == ' '  &&  c && lim;   c = getMsgChar())
  783.     {
  784.     if (lim)
  785.       {
  786.       *dest++ = c;   lim--;
  787.  
  788.       }
  789.  
  790.     }
  791.   /* step through word: */
  792.   for (   ;  c != ' ' && c && lim;   c = getMsgChar())
  793.     {
  794.     if (lim)
  795.       {
  796.       *dest++ = c;   lim--;
  797.  
  798.       }
  799.  
  800.     }
  801.   /* trailing blanks: */
  802.   for (   ;   c == ' ' && c && lim;   c = getMsgChar())
  803.     {
  804.     if (lim)
  805.       {
  806.       *dest++ = c;   lim--;
  807.  
  808.       }
  809.  
  810.     }
  811.   if (c)  unGetMsgChar(c);    /* took one too many    */
  812.   *dest = '\0';        /* tie off string       */
  813.   return  c;
  814.  
  815.   }
  816. /*
  817. * msgInit()
  818. *
  819. * This sets up lowId, highId, cfg.catSector and cfg.catChar, by scanning over
  820. * ctdlmsg.sys.
  821. */
  822. void msgInit()
  823.   {
  824.   MSG_NUMBER first, here;
  825.   CheckPoint Cpt;
  826.   FILE *fd;
  827.   extern struct mBuf mFile1;
  828.   if ((fd = fopen(CHECKPT, READ_ANY)) != NULL)
  829.     {
  830.     fread(&Cpt, sizeof Cpt, 1, fd);
  831.     fclose(fd);
  832.     if (findMessage(Cpt.loc, Cpt.ltnewest, TRUE))
  833.       {
  834.       do
  835.         {
  836.         printf("message# %s\r", msgBuf.mbId);
  837.         while (dGetWord(msgBuf.mbtext, MAXTEXT));
  838.         cfg.catSector   = mFile1.thisSector;
  839.         cfg.catChar     = mFile1.thisChar;
  840.         cfg.newest      = atol(msgBuf.mbId);
  841.         getMessage(getMsgChar, FALSE, FALSE, TRUE);
  842.  
  843.         }
  844.       while (atol(msgBuf.mbId) >= Cpt.ltnewest);
  845.       cfg.oldest = atol(msgBuf.mbId);
  846.       printf("\n\noldest=%lu\n", cfg.oldest);
  847.       printf("newest=%lu\n", cfg.newest);
  848.       return;
  849.  
  850.       }
  851.  
  852.     }
  853.   startAt(msgfl, &mFile1, 0, 0);
  854.   getMessage(getMsgChar, FALSE, FALSE, TRUE);
  855.   /* get the ID# */
  856.   first = atol(msgBuf.mbId);
  857.   printf("message# %lu\n", first);
  858.   cfg.newest = cfg.oldest = first;
  859.   cfg.catSector   = mFile1.thisSector;
  860.   cfg.catChar     = mFile1.thisChar;
  861.   for (getMessage(getMsgChar, FALSE, FALSE, TRUE);
  862.   here = atol(msgBuf.mbId), here != first;
  863.   getMessage(getMsgChar, FALSE, FALSE, TRUE))
  864.     {
  865.     printf("message# %lu\r", here);
  866.     if (strCmpU("Mail", msgBuf.mbroom) == 0) mailCount++;
  867.     /* find highest and lowest message IDs: */
  868.     if (here < cfg.oldest && here != 0l)
  869.       {
  870.       cfg.oldest = here;
  871.  
  872.       }
  873.     if (here > cfg.newest)
  874.       {
  875.       cfg.newest = here;
  876.       /* read rest of message in and remember where it ends,  */
  877.       /* in case it turns out to be the last message    */
  878.       /* in which case, that's where to start writing next message*/
  879.       while (dGetWord(msgBuf.mbtext, MAXTEXT));
  880.       cfg.catSector   = mFile1.thisSector;
  881.       cfg.catChar     = mFile1.thisChar;
  882.  
  883.       }
  884.  
  885.     }
  886.   printf("\n\noldest=%lu\n", cfg.oldest);
  887.   printf("newest=%lu\n", cfg.newest);
  888.  
  889.   }
  890. /*
  891. * zapMsgFile()
  892. *
  893. * This function initializes ctdlmsg.sys.
  894. */
  895. char zapMsgFile()
  896.   {
  897.   extern char *W_R_ANY;
  898.   char cx, fn[80];
  899.   if (!FirstInit)
  900.     {
  901.     printf("\nDestroy all current messages? ");
  902.     cx = simpleGetch();
  903.     if (toUpper(cx) != 'Y')   return FALSE;
  904.  
  905.     }
  906.   if (cfg.BoolFlags.mirror) printf("Creating primary message file.\n");
  907.   if( realZap() )
  908.     {
  909.     if (cfg.BoolFlags.mirror)
  910.       {
  911.       fclose(msgfl);
  912.       makeSysName(fn, "ctdlmsg.sys", &cfg.msg2Area);
  913.       if ((msgfl = fopen(fn, W_R_ANY)) == NULL)
  914.       illegal("?Can't create the secondary message file!");
  915.       printf("Creating secondary message file.\n");
  916.       realZap();
  917.       };
  918.     };
  919.   return TRUE;
  920.  
  921.   }
  922. /*
  923. * realZap()
  924. *
  925. * This does the work of zapMsgFile.
  926. */
  927. char realZap()
  928.   {
  929.   int   i;
  930.   unsigned long sect;
  931.   /* put null message in first sector... */
  932.   sectBuf[0]  = 0xFF; /*   \        */
  933.   sectBuf[1]  =  '1'; /*    >  Message ID "1" MS-DOS style  */
  934.   sectBuf[2]  = '\0'; /*   /        */
  935.   sectBuf[3]  =  'M'; /*   \    Null messsage        */
  936.   sectBuf[4]  = '\0'; /*   /        */
  937.   cfg.newest = cfg.oldest = 1l;
  938.   cfg.catSector   = 0;
  939.   cfg.catChar     = 5;
  940.   for (i=5;  i<MSG_SECT_SIZE;  i++) sectBuf[i] = 0;
  941.   crypte(sectBuf, MSG_SECT_SIZE, 0);       /* encrypt      */
  942.   if (fwrite(sectBuf, MSG_SECT_SIZE, 1, msgfl) != 1)
  943.     {
  944.     printf("zapMsgFil: write failed\n");
  945.     return FALSE;
  946.     }
  947.   crypte(sectBuf, MSG_SECT_SIZE, 0);       /* decrypt      */
  948.   sectBuf[0] = 0;
  949.   crypte(sectBuf, MSG_SECT_SIZE, 0);       /* encrypt      */
  950.   printf("\n%d sectors to be cleared\n", cfg.maxMSector);
  951.   for (sect = 1l;  sect < cfg.maxMSector;  sect++)
  952.     {
  953.     printf("%07.7lu\r", sect);
  954.     if (fwrite(sectBuf, MSG_SECT_SIZE, 1, msgfl) != 1)
  955.       {
  956.       printf("zapMsgFil: write failed\n");
  957.       return FALSE;
  958.       }
  959.  
  960.     }
  961.   Zap_Nodes_Message_Index();               /* zap last netted message */
  962.   crypte(sectBuf, MSG_SECT_SIZE, 0);       /* decrypt      */
  963.   return TRUE;
  964.  
  965.   }
  966. /*
  967. * indexRooms()
  968. *
  969. * This will build a RAM index to CTDLROOM.SYS, displays stats.
  970. */
  971. void indexRooms()
  972.   {
  973.   int shared_room_count;
  974.   int  goodRoom, m, roomCount, slot, WriteIt;
  975.   zero_struct(roomBuf.rbflags);
  976.   zero_struct(roomBuf.rbArea);
  977.   roomBuf.rbgen = 0;
  978.   roomBuf.rbname[0] = 0;
  979.   roomBuf.rbShareType = 0;
  980.   shared_room_count = 0;
  981.   for (m = 0; m < MSGSPERRM; m++)
  982.     {
  983.     roomBuf.msg[m].rbmsgNo = 0l;
  984.     roomBuf.msg[m].rbmsgLoc = 0;
  985.  
  986.     }
  987.   strCpy(roomBuf.rbname, "Mail");
  988.   roomBuf.rbflags.PUBLIC =
  989.   roomBuf.rbflags.PERMROOM =
  990.   roomBuf.rbflags.INUSE = TRUE;
  991.   putRoom(MAILROOM);
  992.   roomCount = 0;
  993.   for (slot = 0;  slot < MAXROOMS;  slot++)
  994.     {
  995.     getRoom(slot);
  996.     printf("Checking room #%3d: ", slot);
  997.     WriteIt = FALSE;
  998.     if (roomBuf.rbflags.INUSE == 1)
  999.       {
  1000.       WriteIt = TRUE;
  1001.       roomBuf.rbflags.INUSE = 0;    /* clear "inUse" flag */
  1002.       if (roomBuf.rbFlIndex >= (int) FloorSize)
  1003.       roomBuf.rbFlIndex = 0;
  1004.       for (m = 0, goodRoom = FALSE; m < MSGSPERRM && !goodRoom; m++)
  1005.         {
  1006.         if (roomBuf.msg[m].rbmsgNo > cfg.oldest)
  1007.           {
  1008.           goodRoom    = TRUE;
  1009.  
  1010.           }
  1011.  
  1012.         }
  1013.       if (goodRoom   || roomBuf.rbflags.PERMROOM == 1)
  1014.         {
  1015.         roomBuf.rbflags.INUSE = 1;
  1016.  
  1017.         }
  1018.       if (roomBuf.rbflags.INUSE == 1)
  1019.         {
  1020.         if (slot == 0)         /* Ugly kludge */
  1021.         strCpy(roomBuf.rbname, baseRoom);
  1022.         roomCount++;
  1023.  
  1024.         }
  1025.       else
  1026.         {
  1027.         zero_struct(roomBuf.rbflags);
  1028.  
  1029.         }
  1030.       }
  1031.       else
  1032.         {
  1033.         noteRoom();
  1034.  
  1035.       }
  1036.     printf("%-25s\r",
  1037.     (roomBuf.rbflags.INUSE == 1) ? roomBuf.rbname : "<not in use>");
  1038.     if (WriteIt)
  1039.       {
  1040.       if (roomBuf.rbflags.INUSE && roomBuf.rbflags.SHARED)
  1041.         {
  1042.         shared_room_count++;
  1043.         roomTab[slot].rtlastNet = findHighestNative();
  1044.         }
  1045.       else roomTab[slot].rtlastNet = 0l;
  1046.       noteRoom();
  1047.       putRoom(slot);
  1048.  
  1049.       }
  1050.  
  1051.     }
  1052.   if( SHARED_ROOMS < shared_room_count )
  1053.     {
  1054.     fprintf(stderr,"***Serious Error***\n");
  1055.     fprintf(stderr," You have #SHARED-ROOMS %d in the ctdlcnfg.sys\n",SHARED_ROOMS);
  1056.     fprintf(stderr," There are %d rooms marked shared\n",shared_room_count);
  1057.     fprintf(stderr," Immediately, run DATACHNG and increase your number of shared rooms above %d\n",SHARED_ROOMS);
  1058.     fprintf(stderr," You might trash your system if you don't\n");
  1059.     illegal("Fatal Error");
  1060.     };
  1061.   printf("\n %d of %d rooms in use\n", roomCount, MAXROOMS);
  1062.  
  1063.   }
  1064. /*
  1065. * findHighestNative()
  1066. *
  1067. * This finds the highest native message in a room.
  1068. */
  1069. MSG_NUMBER findHighestNative()
  1070.   {
  1071.   int rover;
  1072.   MSG_NUMBER ourHighest;
  1073.   theMessages *temp;
  1074.   temp = (theMessages *) GetDynamic(MSG_BULK);
  1075.   copy_ptr(roomBuf.msg, temp, MSGSPERRM);
  1076.   qsort(temp, MSGSPERRM, sizeof temp[0], msgSort);
  1077.   ourHighest = 0l;
  1078.   for (rover = 0; rover < MSGSPERRM; rover++)
  1079.     {
  1080.     if (temp[rover].rbmsgNo != 0l &&
  1081.     temp[rover].rbmsgNo >= cfg.oldest &&
  1082.     temp[rover].rbmsgNo <= cfg.newest &&
  1083.     cfindMessage(temp[rover].rbmsgLoc, temp[rover].rbmsgNo))
  1084.       {
  1085.       if (strCmpU(msgBuf.mbaddr, R_SH_MARK) == SAMESTRING ||
  1086.       strCmpU(msgBuf.mbaddr, NON_LOC_NET) == SAMESTRING)
  1087.         {
  1088.         ourHighest = temp[rover].rbmsgNo;
  1089.         break;
  1090.  
  1091.         }
  1092.  
  1093.       }
  1094.  
  1095.     }
  1096.   free(temp);
  1097.   return ourHighest;
  1098.  
  1099.   }
  1100. /*
  1101. * msgSort()
  1102. *
  1103. * This function sorts messages by their native msg id.
  1104. */
  1105. int msgSort(theMessages *s1, theMessages *s2)
  1106.   {
  1107.   if (s1->rbmsgNo < s2->rbmsgNo) return 1;
  1108.   if (s1->rbmsgNo > s2->rbmsgNo) return -1;
  1109.   return 0;
  1110.  
  1111.   }
  1112. /*
  1113. * noteRoom()
  1114. *
  1115. * This function will enter room into RAM index array.
  1116. */
  1117. void noteRoom()
  1118.   {
  1119.   int   i;
  1120.   MSG_NUMBER last;
  1121.   last = 0l;
  1122.   for (i = 0;  i < MSGSPERRM;  i++)
  1123.     {
  1124.     if (roomBuf.msg[i].rbmsgNo > cfg.newest)
  1125.       {
  1126.       roomBuf.msg[i].rbmsgNo = 0l;
  1127.  
  1128.       }
  1129.     if (roomBuf.msg[i].rbmsgNo > last)
  1130.       {
  1131.       last = roomBuf.msg[i].rbmsgNo;
  1132.  
  1133.       }
  1134.  
  1135.     }
  1136.   roomTab[thisRoom].rtlastMessage = last     ;
  1137.   roomTab[thisRoom].rtShareType   = roomBuf.rbShareType;
  1138.   strCpy(roomTab[thisRoom].rtname, roomBuf.rbname) ;
  1139.   roomTab[thisRoom].rtgen     = roomBuf.rbgen  ;
  1140.   roomTab[thisRoom].rtFlIndex = roomBuf.rbFlIndex;
  1141.   copy_struct(roomBuf.rbflags, roomTab[thisRoom].rtflags);
  1142.  
  1143.   }
  1144. /*
  1145. * zapRoomFile()
  1146. *
  1147. * This function erases and re-initializes CTDLROOM.SYS.
  1148. */
  1149. char zapRoomFile()
  1150.   {
  1151.   int i;
  1152.   char cx;
  1153.   if (!FirstInit)
  1154.     {
  1155.     printf("\nWipe room file? ");
  1156.     cx = simpleGetch();
  1157.     if (toUpper(cx) != 'Y') return FALSE;
  1158.     printf("\n");
  1159.  
  1160.     }
  1161.   zero_struct(roomBuf.rbflags);
  1162.   roomBuf.rbgen     = 0;
  1163.   roomBuf.rbname[0] = 0;   /* unnecessary -- but I like it...  */
  1164.   for (i = 0;  i < MSGSPERRM;  i++)
  1165.     {
  1166.     roomBuf.msg[i].rbmsgNo =  0l;
  1167.     roomBuf.msg[i].rbmsgLoc = 0 ;
  1168.  
  1169.     }
  1170.   printf("maxrooms=%d\n", MAXROOMS);
  1171.   for (thisRoom = 0;  thisRoom < MAXROOMS;  thisRoom++)
  1172.     {
  1173.     printf("clearing room %d\r", thisRoom);
  1174.     RoomSys(thisRoom);
  1175.     putRoom(thisRoom);
  1176.     noteRoom();
  1177.  
  1178.     }
  1179.   printf("\n");
  1180.   /* Lobby> always exists -- guarantees us a place to stand! */
  1181.   thisRoom      = 0      ;
  1182.   strCpy(roomBuf.rbname, baseRoom)    ;
  1183.   roomBuf.rbflags.PERMROOM = TRUE;
  1184.   roomBuf.rbflags.PUBLIC   = TRUE;
  1185.   roomBuf.rbflags.INUSE    = TRUE;
  1186.   RoomSys(0);
  1187.   putRoom(LOBBY);
  1188.   noteRoom();
  1189.   /* Mail> is also permanent...       */
  1190.   thisRoom      = MAILROOM      ;
  1191.   strCpy(roomBuf.rbname, "Mail")      ;
  1192.   RoomSys(1);
  1193.   /* Don't bother to copy flags, they remain the same (right?)    */
  1194.   putRoom(MAILROOM);
  1195.   noteRoom();
  1196.   /* Aide> also...    */
  1197.   thisRoom      = AIDEROOM      ;
  1198.   strCpy(roomBuf.rbname, "Aide")      ;
  1199.   roomBuf.rbflags.PERMROOM = TRUE;
  1200.   roomBuf.rbflags.PUBLIC   = FALSE;
  1201.   roomBuf.rbflags.INUSE    = TRUE;
  1202.   RoomSys(2);
  1203.   putRoom(AIDEROOM);
  1204.   noteRoom();
  1205.   return TRUE;
  1206.  
  1207.   }
  1208. /*
  1209. * logInit()
  1210. *
  1211. * This function indexes ctdllog.sys.
  1212. */
  1213. void logInit()
  1214.   {
  1215.   int i;
  1216.   int count = 0;
  1217.   #ifdef IS_RIGHT
  1218.   if (rewind(logfl) != 0) illegal("Rewinding logfl failed!");
  1219.   #else
  1220.   rewind(logfl);
  1221.   #endif
  1222.   /* clear logTab */
  1223.   for (i = 0; i < cfg.MAXLOGTAB; i++) logTab[i].ltnewest = 0l;
  1224.   /* load logTab: */
  1225.   for (thisLog = 0;  thisLog < cfg.MAXLOGTAB;  thisLog++)
  1226.     {
  1227.     printf("log #%04d", thisLog);
  1228.     getLog(&logBuf, thisLog);
  1229.     /* count valid entries:      */
  1230.     if (logBuf.lbflags.L_INUSE == 1)
  1231.       {
  1232.       count++;
  1233.       printf("%-25s \r", logBuf.lbname);
  1234.  
  1235.       }
  1236.     else printf("%-25s \r","<not in use>");
  1237.     /* copy relevant info into index:   */
  1238.     logTab[thisLog].ltnewest = logBuf.lbvisit[0];
  1239.     logTab[thisLog].ltlogSlot= thisLog;
  1240.     if (logBuf.lbflags.L_INUSE == 1)
  1241.       {
  1242.       logTab[thisLog].ltnmhash = hash(logBuf.lbname);
  1243.       logTab[thisLog].ltpwhash = hash(logBuf.lbpw  );
  1244.       logTab[thisLog].ltpermanent = logBuf.lbflags.PERMANENT;
  1245.  
  1246.       }
  1247.     else
  1248.       {
  1249.       logTab[thisLog].ltnmhash = 0;
  1250.       logTab[thisLog].ltpwhash = 0;
  1251.  
  1252.       }
  1253.  
  1254.     }
  1255.   printf("\n logInit--%d valid log entries\n", count);
  1256.   printf("sort Log...\n");
  1257.   qsort(logTab, cfg.MAXLOGTAB, cfg.sizeLTentry, logSort);
  1258.  
  1259.   }
  1260. /*
  1261. * logSort()
  1262. *
  1263. * This function Sorts 2 entries in logTab.
  1264. */
  1265. int logSort(LogTable *s1, LogTable *s2)
  1266.   {
  1267.   if (s1->ltnmhash == 0 && s2->ltnmhash == 0)  return 0;
  1268.   if (s1->ltnmhash == 0 && s2->ltnmhash != 0)  return 1;
  1269.   if (s1->ltnmhash != 0 && s2->ltnmhash == 0)  return -1;
  1270.   if (s1->ltnewest < s2->ltnewest)  return 1;
  1271.   if (s1->ltnewest > s2->ltnewest)  return -1;
  1272.   return 0;
  1273.  
  1274.   }
  1275. /*
  1276. * noteLog()
  1277. *
  1278. * This notes a logTab entry in RAM buffer in master index.
  1279. */
  1280. void noteLog()
  1281.   {
  1282.   int i, slot;
  1283.   /* figure out who it belongs between: */
  1284.   for (i = 0;  logTab[i].ltnewest > logBuf.lbvisit[0];  i++);
  1285.   /* note location and open it up:  */
  1286.   slot = i;
  1287.   slideLTab(slot, cfg.MAXLOGTAB-1);
  1288.   /* insert new record */
  1289.   logTab[slot].ltnewest       = logBuf.lbvisit[0]  ;
  1290.   logTab[slot].ltlogSlot      = thisLog     ;
  1291.   logTab[slot].ltpwhash       = hash(logBuf.lbpw)  ;
  1292.   logTab[slot].ltnmhash       = hash(logBuf.lbname);
  1293.  
  1294.   }
  1295. /*
  1296. * slideLTab()
  1297. *
  1298. * This function slides bottom N slots in logTab down.  For sorting.
  1299. */
  1300. void slideLTab(int slot, int last)
  1301.   {
  1302.   int i;
  1303.   /* open slot up: (movmem isn't guaranteed on overlaps) */
  1304.   for (i = last - 1;  i >= slot;  i--)
  1305.     {
  1306.     movmem(&logTab[i], &logTab[i + 1], cfg.sizeLTentry);
  1307.  
  1308.     }
  1309.  
  1310.   }
  1311. /*
  1312. * wrapup()
  1313. *
  1314. * This finishes up and writes ctdlTabl.sys out, finally.
  1315. */
  1316. void wrapup(char onlyParams)
  1317.   {
  1318.   printf("\ncreating ctdlTabl.sys table\n");
  1319.   if (!onlyParams)
  1320.     {
  1321.     if (!msgZap)  msgInit();
  1322.     if (!roomZap) indexRooms();
  1323.     cfg.weAre = CITADEL;
  1324.     if (!logZap)  logInit();
  1325.     netInit();
  1326.     if (mailCount)
  1327.     printf("%d of the messages were Mail\n", mailCount);
  1328.  
  1329.     }
  1330.   EventTab = (EVENT *) GetDynamic(cfg.EvNumber * sizeof *EventTab);
  1331.   if (!FinalSystemCheck(onlyParams)) exit(2);
  1332.   if (!onlyParams)
  1333.     {
  1334.     if (cfg.BoolFlags.netParticipant)
  1335.     fclose(netfl);
  1336.     fclose(roomfl);
  1337.     fclose(msgfl);
  1338.     fclose(logfl);
  1339.  
  1340.     }
  1341.   RunList(&Events, EventWrite); /* because we keep this in a linked list */
  1342.   printf("writeSysTab = %d\n", writeSysTab());
  1343.  
  1344.   }
  1345. /*
  1346. * zapLogFile()
  1347. *
  1348. * This erases & re-initializes ctdllog.sys.
  1349. */
  1350. char zapLogFile()
  1351.   {
  1352.   int  i;
  1353.   char cx;
  1354.   if (!FirstInit)
  1355.     {
  1356.     printf("\nWipe out log file? ");
  1357.     cx = simpleGetch();
  1358.     if (toUpper(cx) != 'Y')   return FALSE;
  1359.     printf("\n");
  1360.  
  1361.     }
  1362.   /* clear RAM buffer out:      */
  1363.   logBuf.lbflags.L_INUSE = FALSE;
  1364.   for (i = 0;  i < MAILSLOTS;  i++)
  1365.     {
  1366.     logBuf.lbMail[i].rbmsgLoc = 0l;
  1367.     logBuf.lbMail[i].rbmsgNo  = 0l;
  1368.  
  1369.     }
  1370.   for (i = 0;  i < NAMESIZE;  i++)
  1371.     {
  1372.     logBuf.lbname[i] = 0;
  1373.     logBuf.lbpw[i]   = 0;
  1374.  
  1375.     }
  1376.   /* write empty buffer all over file;  */
  1377.   for (i = 0; i < cfg.MAXLOGTAB;  i++)
  1378.     {
  1379.     printf("Clearing log #%d\r", i);
  1380.     putLog(&logBuf, i);
  1381.     logTab[i].ltnewest = logBuf.lbvisit[0];
  1382.     logTab[i].ltlogSlot= i;
  1383.     logTab[i].ltnmhash = hash(logBuf.lbname);
  1384.     logTab[i].ltpwhash = hash(logBuf.lbpw  );
  1385.  
  1386.     }
  1387.   return TRUE;
  1388.  
  1389.   }
  1390. /*
  1391. * netInit()
  1392. *
  1393. * This will Initialize RAM index for Ctdlnet.sys.
  1394. */
  1395. void netInit()
  1396.   {
  1397.   label temp;
  1398.   int i = 0;
  1399.   long length;
  1400.   if (!cfg.BoolFlags.netParticipant) return;
  1401.   totalBytes(&length, netfl);
  1402.   cfg.netSize = (int) (length / NB_TOTAL_SIZE);
  1403.   if (cfg.netSize)
  1404.   netTab = (NetTable *) GetDynamic(sizeof (*netTab) * cfg.netSize);
  1405.   else
  1406.   netTab = NULL;
  1407.   while (i < cfg.netSize)
  1408.     {
  1409.     getNet(i, &netBuf);
  1410.     netTab[i].netTRooms = (SharedRoom *)
  1411.     GetDynamic(sizeof (*netBuf.netRooms) * SHARED_ROOMS);
  1412.     normId(netBuf.netId, temp);
  1413.     netTab[i].ntnmhash = hash(netBuf.netName);
  1414.     netTab[i].ntidhash = hash(temp);
  1415.     strCpy(netTab[i].ntShort, netBuf.nbShort);
  1416.     copy_struct(netBuf.nbflags, netTab[i].ntflags);
  1417.     movmem(netBuf.netRooms, netTab[i].netTRooms,
  1418.     sizeof *netBuf.netRooms * SHARED_ROOMS);
  1419.     netTab[i].ntMemberNets = netBuf.MemberNets;
  1420.     printf("System %3d. %s\n", i,
  1421.     (netBuf.nbflags.in_use) ? netBuf.netName : "<not in use>");
  1422.     i++;
  1423.  
  1424.     }
  1425.   if (cfg.MailHub != 0)
  1426.     {
  1427.     if (searchNameNet(cfg.MailHub + cfg.codeBuf, &netBuf) == -1)
  1428.     illegal("Your #MailHub node was not found in your CtdlNet.Sys.");
  1429.     if (netBuf.nbRoute != -1 &&
  1430.     netTab[netBuf.nbRoute].ntGen == netBuf.nbRouteGen)
  1431.     illegal("You must have a direct connect to your #MailHub.");
  1432.  
  1433.     }
  1434.  
  1435.   }
  1436. /*
  1437. * strCmpU()
  1438. *
  1439. * This is strcmp(), but ignoring case distinctions.  Found in most C libraries
  1440. * as stricmp().  Someday we should switch over.
  1441. */
  1442. int strCmpU(char s[], char t[])
  1443.   {
  1444.   int  i;
  1445.   i = 0;
  1446.   while (toUpper(s[i]) == toUpper(t[i]))
  1447.     {
  1448.     if (s[i++] == '\0')  return SAMESTRING ;
  1449.  
  1450.     }
  1451.   return  toUpper(s[i]) - toUpper(t[i]);
  1452.  
  1453.   }
  1454. /*
  1455. * crashout()
  1456. *
  1457. * This handles a fatal error, for library functions.
  1458. */
  1459. void crashout(char *str)
  1460.   {
  1461.   illegal(str);
  1462.  
  1463.   }
  1464. /*
  1465. * cfindMessage()
  1466. *
  1467. * This function gets all set up to do something with a message.
  1468. */
  1469. char cfindMessage(SECTOR_ID loc, MSG_NUMBER id)
  1470.   {
  1471.   long atol();
  1472.   MSG_NUMBER here;
  1473.   extern struct mBuf mFile1;
  1474.   startAt(msgfl, &mFile1, loc, 0);
  1475.   do
  1476.     {
  1477.     getMessage(getMsgChar, FALSE, FALSE, TRUE);
  1478.     here = atol(msgBuf.mbId);
  1479.  
  1480.     }
  1481.   while (here != id &&  mFile1.thisSector == loc);
  1482.   return (char)((here == id));
  1483.  
  1484.   }
  1485. /*
  1486. * CheckFloors()
  1487. *
  1488. * This function will check the floors.
  1489. */
  1490. void CheckFloors()
  1491.   {
  1492.   SYS_FILE     tempName;
  1493.   FILE   *flrfl;
  1494.   struct floor FloorBuf;
  1495.   struct floor *fptr;
  1496.   extern char  *R_W_ANY, *WRITE_ANY;
  1497.   int rover, cindex;
  1498.   char *cptr;
  1499.  
  1500.   makeSysName(tempName, "ctdlflr.sys", &cfg.floorArea);
  1501.  
  1502.   if ((flrfl = fopen(tempName, R_W_ANY)) == NULL)
  1503.     {
  1504.     printf(" %s not found, creating new file.\n", tempName);
  1505.     if ((flrfl = fopen(tempName, WRITE_ANY)) == NULL)
  1506.     illegal("?Can't create the floor file!");
  1507.  
  1508.     }
  1509.   /** create initial floor entry **/
  1510.   strCpy(FloorBuf.FlName, cfg.codeBuf + cfg.MainFloor);
  1511.   FloorBuf.FlInuse = TRUE;
  1512.   memset(FloorBuf.FlModerator, '\0',sizeof(label));
  1513.   /** write floor creation entry **/
  1514.   if( fwrite(&FloorBuf, sizeof FloorBuf, 1, flrfl) != 1)
  1515.     {
  1516.     printf("Write Error: %s\n",tempName);
  1517.     };
  1518.   totalBytes(&FloorSize, flrfl);
  1519.   FloorSize /= sizeof FloorBuf;
  1520.   printf("Current Floor file size is %ld entries\n",FloorSize);
  1521.   fclose(flrfl);
  1522.   /*  strip unused records  */
  1523.   if ((flrfl = fopen(tempName, READ_ANY)) == NULL)
  1524.     {
  1525.     illegal("?Can't read the floor file!");
  1526.     };
  1527.   fptr = (struct floor *)malloc(FloorSize * sizeof(struct floor) );
  1528.   /* get buffer for whole file */
  1529.   if( fptr == NULL )
  1530.     {
  1531.     free(fptr);
  1532.     illegal(" cannot allocate memory for a floor file!");
  1533.     };
  1534.   /* read whole file */
  1535.   if( fread( fptr, sizeof(struct floor), FloorSize, flrfl) != FloorSize )
  1536.     {
  1537.     free(fptr);
  1538.     illegal("Unable to read floor file!");
  1539.     };
  1540.   fclose(flrfl);
  1541.   /* Now, we know that there is at least one good record so we
  1542.      check from the end until we find a record in use
  1543.   */
  1544.   for( rover = 0; rover < FloorSize && fptr[rover].FlInuse  == TRUE; rover++)
  1545.     {
  1546.     /* validate that the Name are alpha characters and
  1547.        printable. Also test to see if In use.
  1548.     */
  1549.     cptr = &fptr[rover].FlModerator[0];
  1550.     if( ( *cptr >= 'a' && *cptr <= 'z' ) || ( *cptr >= 'A' && *cptr <= 'Z' ) )
  1551.       {
  1552.       printf("%20s is moderator for %s\n",fptr[rover].FlModerator,fptr[rover].FlName);
  1553.       }
  1554.     else
  1555.       {
  1556.       for( cindex = 0; cindex <20 ; cindex++)
  1557.         {
  1558.         cptr[cindex] = '\0';
  1559.         };
  1560.       };
  1561.     };
  1562.   FloorSize = rover;
  1563.   printf("New Floor file size is %ld entries\n",FloorSize);
  1564.   if ((flrfl = fopen(tempName, W_R_ANY)) == NULL)
  1565.     {
  1566.     free(fptr);
  1567.     illegal("?Can't Open the floor file to re-write!");
  1568.     };
  1569.   if( fwrite(fptr, sizeof(struct floor), FloorSize, flrfl) != FloorSize)
  1570.     {
  1571.     printf("Write Error: %s\n",tempName);
  1572.     };
  1573.   free(fptr);
  1574.   fclose(flrfl);
  1575.   }
  1576. /*
  1577. * CheckNet()
  1578. *
  1579. * This creates the Ctdlnet.sys if needed.
  1580. */
  1581. void CheckNet()
  1582.   {
  1583.   SYS_FILE      tempName;
  1584.   makeSysName(tempName, "ctdlnet.sys", &cfg.netArea);
  1585.   if ((netfl = fopen(tempName, READ_ANY)) == NULL)
  1586.     {
  1587.     printf(" %s not found, creating new file.\n", tempName);
  1588.     if ((netfl = fopen(tempName, WRITE_ANY)) == NULL)
  1589.     illegal("?Can't create the net file!");
  1590.  
  1591.     }
  1592.  
  1593.   }
  1594. /*
  1595. * NetParse()
  1596. *
  1597. * This function is responsible for parsing the network parameters.
  1598. */
  1599. static char NetParse(char *line, int *offset, char *var, int arg, int SetVal)
  1600.   {
  1601.   char temp[100];
  1602.   if (strCmpU(var, "#NewNetPrivs")    == SAMESTRING)
  1603.     {
  1604.     cfg.BoolFlags.NetDft      = arg;
  1605.     return TRUE;
  1606.  
  1607.     }
  1608.   else if (strCmpU(var, "#RouteMail")     == SAMESTRING)
  1609.     {
  1610.     cfg.BoolFlags.RouteMail = arg;
  1611.     return TRUE;
  1612.  
  1613.     }
  1614.   else if (strCmpU(var, "#SCAN-NET-MESSAGES") == SAMESTRING)
  1615.     {
  1616.     cfg.BoolFlags.NetScanBad = TRUE;
  1617.     return TRUE;
  1618.  
  1619.     }
  1620.   else if (strCmpU(var, "#SHARED-ROOMS")  == SAMESTRING)
  1621.     {
  1622.     if (SetVal)
  1623.       {
  1624.       if (SHARED_ROOMS != arg && cfg.netSize != 0)
  1625.       illegal(
  1626.       "SHARED-ROOMS parameter does not equal old value!");
  1627.       else
  1628.       SHARED_ROOMS = arg;
  1629.  
  1630.       }
  1631.     else
  1632.       {
  1633.       SHARED_ROOMS = arg;
  1634.  
  1635.       }
  1636.     return TRUE;
  1637.  
  1638.     }
  1639.   else if (strCmpU(var, "#NETWORK"   )    == SAMESTRING)
  1640.     {
  1641.     cfg.BoolFlags.netParticipant = arg;
  1642.     return TRUE;
  1643.     #ifdef NEED_LONGHAUL
  1644.  
  1645.     }
  1646.   else if (strCmpU(var, "#LONG-HAUL" )    == SAMESTRING)
  1647.     {
  1648.     cfg.BoolFlags.longHaul = arg;
  1649.     return TRUE;
  1650.     #endif
  1651.  
  1652.     }
  1653.   else if (strCmpU(var, "#NET_AREA_SIZE") == SAMESTRING)
  1654.     {
  1655.     cfg.sizeArea = arg;
  1656.     return TRUE;
  1657.  
  1658.     }
  1659.   else if (strCmpU(var, "#MAX_NET_FILE")    == SAMESTRING)
  1660.     {
  1661.     cfg.maxFileSize = arg;
  1662.     return TRUE;
  1663.  
  1664.     }
  1665.   else if (strCmpU(var, "#callOutSuffix") == SAMESTRING)
  1666.     {
  1667.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1668.     cfg.netSuffix = *offset;
  1669.     while (cfg.codeBuf[*offset])
  1670.     (*offset)++;
  1671.     (*offset)++;
  1672.     return TRUE;
  1673.  
  1674.     }
  1675.   else if (strCmpU(var, "#callOutPrefix") == SAMESTRING)
  1676.     {
  1677.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1678.     DefaultPrefix = *offset;
  1679.     while (cfg.codeBuf[*offset])
  1680.     (*offset)++;
  1681.     (*offset)++;
  1682.     return TRUE;
  1683.  
  1684.     }
  1685.   else if (strCmpU(var, "#DialOut300") == SAMESTRING)
  1686.     {
  1687.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1688.     cfg.DialPrefixes[ONLY_300] = *offset;
  1689.     while (cfg.codeBuf[*offset])
  1690.     (*offset)++;
  1691.     (*offset)++;
  1692.     return TRUE;
  1693.  
  1694.     }
  1695.   else if (strCmpU(var, "#DialOut1200") == SAMESTRING)
  1696.     {
  1697.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1698.     cfg.DialPrefixes[BOTH_300_1200] = *offset;
  1699.     while (cfg.codeBuf[*offset])
  1700.     (*offset)++;
  1701.     (*offset)++;
  1702.     return TRUE;
  1703.  
  1704.     }
  1705.   else if (strCmpU(var, "#DialOut2400") == SAMESTRING)
  1706.     {
  1707.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1708.     cfg.DialPrefixes[TH_3_12_24] = *offset;
  1709.     while (cfg.codeBuf[*offset])
  1710.     (*offset)++;
  1711.     (*offset)++;
  1712.     return TRUE;
  1713.  
  1714.     }
  1715.   else if (strCmpU(var, "#DialOut4800") == SAMESTRING)
  1716.     {
  1717.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1718.     cfg.DialPrefixes[B_4] = *offset;
  1719.     while (cfg.codeBuf[*offset])
  1720.     (*offset)++;
  1721.     (*offset)++;
  1722.     return TRUE;
  1723.  
  1724.     }
  1725.   else if (strCmpU(var, "#DialOut9600") == SAMESTRING)
  1726.     {
  1727.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1728.     cfg.DialPrefixes[B_5] = *offset;
  1729.     while (cfg.codeBuf[*offset])
  1730.     (*offset)++;
  1731.     (*offset)++;
  1732.     return TRUE;
  1733.  
  1734.     }
  1735.   else if (strCmpU(var, "#DialOut14400") == SAMESTRING)
  1736.     {
  1737.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1738.     cfg.DialPrefixes[B_6] = *offset;
  1739.     while (cfg.codeBuf[*offset])
  1740.     (*offset)++;
  1741.     (*offset)++;
  1742.     return TRUE;
  1743.  
  1744.     }
  1745.   else if (strCmpU(var, "#DialOut19200") == SAMESTRING)
  1746.     {
  1747.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1748.     cfg.DialPrefixes[B_7] = *offset;
  1749.     while (cfg.codeBuf[*offset])
  1750.     (*offset)++;
  1751.     (*offset)++;
  1752.     return TRUE;
  1753.  
  1754.     }
  1755.   else if (strCmpU(var, "#nodeName" ) == SAMESTRING)
  1756.     {
  1757.     readString(line, &cfg.codeBuf[*offset], FALSE);
  1758.     NormStr(&cfg.codeBuf[*offset]);
  1759.     if (strLen(&cfg.codeBuf[*offset]) > 19)
  1760.     illegal("nodeName too long; must be less than 20");
  1761.     if (strchr(&cfg.codeBuf[*offset], '_') != NULL ||
  1762.     strchr(&cfg.codeBuf[*offset], '.') != NULL)
  1763.     illegal("The characters '.' and '_' are illegal in node names!");
  1764.     cfg.nodeName    = *offset;
  1765.     while (cfg.codeBuf[*offset]) /* step over string     */
  1766.     (*offset)++;
  1767.     (*offset)++;
  1768.     return TRUE;
  1769.  
  1770.     }
  1771.   else if (strCmpU(var, "#nodeId"   ) == SAMESTRING)
  1772.     {
  1773.     readString(line, &cfg.codeBuf[*offset], FALSE);
  1774.     if (strLen(&cfg.codeBuf[*offset]) > 19)
  1775.     illegal("nodeId too long; must be less than 20");
  1776.     cfg.nodeId      = *offset;
  1777.     while (cfg.codeBuf[*offset]) /* step over string     */
  1778.     (*offset)++;
  1779.     (*offset)++;
  1780.     return TRUE;
  1781.  
  1782.     }
  1783.   else if (strCmpU(var, "#MailHub"  ) == SAMESTRING)
  1784.     {
  1785.     readString(line, &cfg.codeBuf[*offset], FALSE);
  1786.     if (strLen(&cfg.codeBuf[*offset]) > 19)
  1787.     illegal("MailHub too long; must be less than 20");
  1788.     cfg.MailHub      = *offset;
  1789.     while (cfg.codeBuf[*offset]) /* step over string     */
  1790.     (*offset)++;
  1791.     (*offset)++;
  1792.     return TRUE;
  1793.  
  1794.     }
  1795.   else if (strCmpU(var, "#DomainDisplay") == SAMESTRING)
  1796.     {
  1797.     readString(line, cfg.DomainDisplay, FALSE);
  1798.     if (strLen(cfg.DomainDisplay) >= sizeof cfg.DomainDisplay)
  1799.     illegal("DomainDisplay is too long, must be less than 11");
  1800.     return TRUE;
  1801.  
  1802.     }
  1803.   else if (strCmpU(var, "#nodeDomain") == SAMESTRING)
  1804.     {
  1805.     readString(line, &cfg.codeBuf[*offset], FALSE);
  1806.     if (strLen(&cfg.codeBuf[*offset]) > 19)
  1807.     illegal("nodeDomain too long; must be less than 20");
  1808.     if (strchr(cfg.codeBuf + *offset, '_') != NULL ||
  1809.     strchr(cfg.codeBuf + *offset, '.') != NULL)
  1810.     illegal("Domain names cannot have '_' or '.' in them.");
  1811.     cfg.nodeDomain = *offset;
  1812.     while (cfg.codeBuf[*offset]) /* step over string     */
  1813.     (*offset)++;
  1814.     (*offset)++;
  1815.     return TRUE;
  1816.  
  1817.     }
  1818.   else if (strCmpU(var, "#ServeDomain") == SAMESTRING)
  1819.     {
  1820.     readString(line, temp, FALSE);
  1821.     if (strLen(temp) > 19)
  1822.     illegal("ServeDomain value is too long, must be less than 19 characters.");
  1823.     AddData(&Serves, strdup(temp), NULL, FALSE);
  1824.     cfg.DomainHandlers++;
  1825.     return TRUE;
  1826.  
  1827.     }
  1828.   return FALSE;
  1829.  
  1830.   }
  1831.  
  1832. void  Zap_Nodes_Message_Index()  /* zap last netted message */
  1833.   {
  1834.   int node, slot;
  1835.   for(node = 0; node < cfg.netSize; node++)
  1836.     {
  1837.     if( !netTab[node].ntflags.in_use )continue;
  1838.     getNet(node,&netBuf);
  1839.     for( slot=0; slot < SHARED_ROOMS; slot++)
  1840.       {
  1841.       if( !roomTab[netTabRoomSlot(node, slot)].rtflags.SHARED)continue;
  1842.       netTab[node].netTRooms[slot].lastMess = 0;
  1843.       netBuf.netRooms[slot].lastMess = 0;
  1844.       };
  1845.     putNet(node,&netBuf);
  1846.     };
  1847.  
  1848.   }
  1849.